﻿using AiMoRhino.ScriptInstance.CustomGetter;
using Rhino;
using Rhino.DocObjects;
using Rhino.Geometry;
using Rhino.Input.Custom;
using System;
using System.Collections.Generic;

namespace AiMoRhino.ScriptInstance.LinkSelect
{
    class LinkedOneItem : LinkedItemBase

    {
        public Guid id = Guid.Empty;

        public override IEnumerable<Guid> AllIDs
        {
            get
            {
                if (id != Guid.Empty) yield return id;
            }
        }
        public override void ClearLink()
        {
            id = Guid.Empty;
        }
        public override bool IsMultiple => false;
        public override bool HasLinkedObject => id != Guid.Empty;

        public RhinoObject ResultRhinoObj { get; private set; } = null;
        public InstanceObject ResultInstanceObj { get; private set; } = null;
        public Point3d ResultPoint { get; private set; } = Point3d.Unset;
        public Polyline ResultPolyline { get; private set; } = null;
        public Circle ResultCircle { get; private set; } = Circle.Unset;
        public Line ResultLine { get; private set; } = Line.Unset;
        public Curve ResultCurve { get; private set; } = null;
        public Mesh ResultMesh { get; private set; } = null;
        public Brep ResultBrep { get; private set; } = null;
        public Extrusion ResultExtrusion { get; private set; } = null;
        public Surface ResultSurface { get; private set; } = null;

        public LinkedOneItem(LinkType currentLinkType) : base(currentLinkType)
        {
        }

        public override bool BuildLink()
        {
            RhinoObject obj = null;
            switch (CurrentLinkType)
            {
                case LinkType.RhinoObject:
                    GetOneObject(out obj, ObjectType.AnyObject, "RhinoObject", new GetObject());
                    break;
                case LinkType.InstanceObject:
                    GetOneObject(out obj, ObjectType.InstanceReference, "Instance Reference", new GetObject());
                    break;
                case LinkType.Point3d:
                    GetOneObject(out obj, ObjectType.Point, "Point3d", new GetObject());
                    break;
                case LinkType.Polyline:
                    GetOneObject(out obj, ObjectType.Curve, "Polyline", new GetPolylineObject());
                    break;
                case LinkType.Circle:
                    GetOneObject(out obj, ObjectType.Curve, "Circle", new GetCircleObject());
                    break;
                case LinkType.Line:
                    GetOneObject(out obj, ObjectType.Curve, "Line", new GetLineObject());
                    break;
                case LinkType.Curve:
                    GetOneObject(out obj, ObjectType.Curve, "Curve", new GetObject());
                    break;
                case LinkType.Brep:
                    GetOneObject(out obj, ObjectType.Brep, "Brep", new GetObject());
                    break;
                case LinkType.Mesh:
                    GetOneObject(out obj, ObjectType.Mesh, "Mesh", new GetObject());
                    break;
                case LinkType.Extrusion:
                    GetOneObject(out obj, ObjectType.Extrusion, "Extrusion", new GetObject());
                    break;
                case LinkType.Surface:
                    GetOneObject(out obj, ObjectType.Surface, "Surface", new GetObject());
                    break;
            }
            if (obj != null)
            {
                id = obj.Id;
                return true;
            }
            else
            {
                id = Guid.Empty;
                return false;
            }
        }

        public override bool GetLinkedGeometry()
        {
            switch (CurrentLinkType)
            {
                case LinkType.RhinoObject:
                    ResultRhinoObj = ToObject();
                    return ResultRhinoObj != null;
                case LinkType.InstanceObject:
                    ResultInstanceObj = ToObject() as InstanceObject;
                    return ResultInstanceObj != null;
                case LinkType.Point3d:
                    return ToPoint3d();
                case LinkType.Polyline:
                    return ToPolyline();
                case LinkType.Circle:
                    return ToCircle();
                case LinkType.Line:
                    return ToLine();
                case LinkType.Curve:
                    return ToCurve();
                case LinkType.Mesh:
                    return ToMesh();
                case LinkType.Brep:
                    return ToBrep();
                case LinkType.Extrusion:
                    return ToExtrusion();
                case LinkType.Surface:
                    return ToSurface();
            }
            return false;
        }
        RhinoObject ToObject()
        {
            return RhinoDoc.ActiveDoc.Objects.FindId(id);
        }
        bool ToPoint3d()
        {
            ResultPoint = Point3d.Unset;
            RhinoObject obj = ToObject();
            if (obj is PointObject ptObj)
            {
                ResultPoint = ptObj.PointGeometry.Location;
            }
            return ResultPoint != Point3d.Unset;
        }
        bool ToPolyline()
        {
            ResultPolyline = null;
            RhinoObject obj = ToObject();
            if (obj is CurveObject curveObj && curveObj.CurveGeometry.TryGetPolyline(out Polyline pl))
            {
                ResultPolyline = pl;
            }
            return ResultPolyline != null;
        }
        bool ToCircle()
        {
            ResultCircle = Circle.Unset;
            RhinoObject obj = ToObject();
            if (obj is CurveObject curveObj && curveObj.CurveGeometry.TryGetCircle(out Circle re))
            {
                ResultCircle = re;
            }
            return ResultCircle.IsValid;
        }
        bool ToLine()
        {
            ResultLine = Line.Unset;
            RhinoObject obj = ToObject();
            if (obj is CurveObject curveObj && curveObj.CurveGeometry.IsLinear())
            {
                ResultLine = new Line(curveObj.CurveGeometry.PointAtStart, curveObj.CurveGeometry.PointAtEnd);
            }
            return ResultLine.IsValid;
        }

        bool ToCurve()
        {
            ResultCurve = null;
            RhinoObject obj = ToObject();
            if (obj is CurveObject crvObj)
            {
                ResultCurve = crvObj.CurveGeometry;
            }
            return ResultCurve != null;
        }

        bool ToMesh()
        {
            ResultMesh = null;
            RhinoObject obj = ToObject();
            if (obj is MeshObject meshObj)
            {
                ResultMesh = meshObj.MeshGeometry;
            }
            return ResultMesh != null;
        }

        bool ToBrep()
        {
            ResultBrep = null;
            RhinoObject obj = ToObject();
            if (obj is BrepObject re)
            {
                ResultBrep = re.BrepGeometry;
            }
            return ResultBrep != null;
        }

        bool ToSurface()
        {
            ResultSurface = null;
            RhinoObject obj = ToObject();
            if (obj is BrepObject re && re.BrepGeometry.Surfaces.Count == 1)
            {
                ResultSurface = re.BrepGeometry.Surfaces[0];
            }

            return ResultSurface != null;
        }

        bool ToExtrusion()
        {
            ResultExtrusion = null;
            RhinoObject obj = ToObject();
            if (obj is ExtrusionObject re)
            {
                ResultExtrusion = re.ExtrusionGeometry;
            }
            return ResultExtrusion != null;
        }
    }
}
